package com.smart.community.commons.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页查询优化工具类
 * 
 * @author Wu.Liang
 * @since 2024-12-21
 */
@Slf4j
public class PageQueryUtils {

    public static final int DEFAULT_PAGE_SIZE = 10;
    public static final int MAX_PAGE_SIZE = 1000;

    /**
     * 过滤操作符
     */
    public enum FilterOperator {
        EQ,    // 等于
        NE,    // 不等于
        GT,    // 大于
        GE,    // 大于等于
        LT,    // 小于
        LE,    // 小于等于
        LIKE,  // 模糊匹配
        IN,    // 包含
        NOT_IN // 不包含
    }

    /**
     * 过滤条件
     */
    public static class FilterCondition {
        private String field;
        private FilterOperator operator;
        private Object value;

        public FilterCondition(String field, FilterOperator operator, Object value) {
            this.field = field;
            this.operator = operator;
            this.value = value;
        }

        public String getField() { return field; }
        public void setField(String field) { this.field = field; }

        public FilterOperator getOperator() { return operator; }
        public void setOperator(FilterOperator operator) { this.operator = operator; }

        public Object getValue() { return value; }
        public void setValue(Object value) { this.value = value; }
    }

    /**
     * 排序字段
     */
    public static class SortField {
        private String field;
        private boolean asc = true;

        public SortField(String field) {
            this.field = field;
        }

        public SortField(String field, boolean asc) {
            this.field = field;
            this.asc = asc;
        }

        public String getField() { return field; }
        public void setField(String field) { this.field = field; }

        public boolean isAsc() { return asc; }
        public void setAsc(boolean asc) { this.asc = asc; }
    }

    /**
     * 创建分页对象
     */
    public static <T> Page<T> createPage(Integer current, Integer size) {
        int currentPage = current != null && current > 0 ? current : 1;
        int pageSize = size != null && size > 0 ? Math.min(size, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;
        return new Page<>(currentPage, pageSize);
    }

    /**
     * 优化分页查询 - 使用索引分页
     */
    public static <T> IPage<T> indexPageQuery(Function<LambdaQueryWrapper<T>, List<T>> queryFunction,
                                            String indexField,
                                            Object indexValue,
                                            Integer size) {
        int limit = size != null && size > 0 ? Math.min(size, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        
        // 设置索引条件 - 使用原生SQL条件
        if (indexValue != null) {
            queryWrapper.apply(indexField + " >= {0}", indexValue);
        }
        
        // 设置排序 - 使用原生SQL排序
        queryWrapper.last("ORDER BY " + indexField + " ASC");
        
        // 设置限制
        queryWrapper.last("LIMIT " + limit);
        
        List<T> results = queryFunction.apply(queryWrapper);
        Page<T> page = new Page<>(1, limit);
        page.setRecords(results);
        page.setTotal(results.size());
        
        return page;
    }

    /**
     * 优化分页查询 - 使用游标分页
     */
    public static <T> IPage<T> cursorPageQuery(Function<LambdaQueryWrapper<T>, List<T>> queryFunction,
                                             String cursorField,
                                             Object cursorValue,
                                             Integer size) {
        int limit = size != null && size > 0 ? Math.min(size, MAX_PAGE_SIZE) : DEFAULT_PAGE_SIZE;
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        
        // 设置游标条件 - 使用原生SQL条件
        if (cursorValue != null) {
            queryWrapper.apply(cursorField + " > {0}", cursorValue);
        }
        
        // 设置排序 - 使用原生SQL排序
        queryWrapper.last("ORDER BY " + cursorField + " ASC");
        
        // 设置限制
        queryWrapper.last("LIMIT " + (limit + 1)); // 多查询一条用于判断是否有下一页
        
        List<T> results = queryFunction.apply(queryWrapper);
        boolean hasNext = results.size() > limit;
        
        if (hasNext) {
            results = results.subList(0, limit);
        }
        
        Page<T> page = new Page<>(1, limit);
        page.setRecords(results);
        page.setTotal(hasNext ? -1 : results.size()); // -1表示未知总数
        
        return page;
    }

    /**
     * 分页查询优化 - 支持过滤条件
     */
    public static <T> IPage<T> filteredPageQuery(Function<LambdaQueryWrapper<T>, IPage<T>> queryFunction,
                                               Integer current,
                                               Integer size,
                                               List<FilterCondition> filters) {
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        
        // 设置过滤条件
        if (filters != null && !filters.isEmpty()) {
            for (FilterCondition filter : filters) {
                applyFilter(queryWrapper, filter);
            }
        }
        
        return queryFunction.apply(queryWrapper);
    }

    /**
     * 分页查询优化 - 支持多字段排序
     */
    public static <T> IPage<T> optimizedPageQuery(Function<LambdaQueryWrapper<T>, IPage<T>> queryFunction,
                                                Integer current,
                                                Integer size,
                                                List<SortField> sortFields) {
        LambdaQueryWrapper<T> queryWrapper = new LambdaQueryWrapper<>();
        
        // 设置排序
        if (sortFields != null && !sortFields.isEmpty()) {
            StringBuilder orderBy = new StringBuilder("ORDER BY ");
            for (int i = 0; i < sortFields.size(); i++) {
                SortField sortField = sortFields.get(i);
                if (i > 0) {
                    orderBy.append(", ");
                }
                orderBy.append(sortField.getField());
                orderBy.append(sortField.isAsc() ? " ASC" : " DESC");
            }
            queryWrapper.last(orderBy.toString());
        }
        
        return queryFunction.apply(queryWrapper);
    }

    /**
     * 应用过滤条件
     */
    private static <T> void applyFilter(LambdaQueryWrapper<T> queryWrapper, FilterCondition filter) {
        if (filter == null || !StringUtils.hasText(filter.getField()) || filter.getValue() == null) {
            return;
        }
        
        switch (filter.getOperator()) {
            case EQ:
                queryWrapper.apply(filter.getField() + " = {0}", filter.getValue());
                break;
            case NE:
                queryWrapper.apply(filter.getField() + " != {0}", filter.getValue());
                break;
            case GT:
                queryWrapper.apply(filter.getField() + " > {0}", filter.getValue());
                break;
            case GE:
                queryWrapper.apply(filter.getField() + " >= {0}", filter.getValue());
                break;
            case LT:
                queryWrapper.apply(filter.getField() + " < {0}", filter.getValue());
                break;
            case LE:
                queryWrapper.apply(filter.getField() + " <= {0}", filter.getValue());
                break;
            case LIKE:
                queryWrapper.apply(filter.getField() + " LIKE {0}", "%" + filter.getValue() + "%");
                break;
            case IN:
                if (filter.getValue() instanceof Collection) {
                    Collection<?> values = (Collection<?>) filter.getValue();
                    if (!values.isEmpty()) {
                        String placeholders = String.join(",", Collections.nCopies(values.size(), "{0}"));
                        queryWrapper.apply(filter.getField() + " IN (" + placeholders + ")", values.toArray());
                    }
                }
                break;
            case NOT_IN:
                if (filter.getValue() instanceof Collection) {
                    Collection<?> values = (Collection<?>) filter.getValue();
                    if (!values.isEmpty()) {
                        String placeholders = String.join(",", Collections.nCopies(values.size(), "{0}"));
                        queryWrapper.apply(filter.getField() + " NOT IN (" + placeholders + ")", values.toArray());
                    }
                }
                break;
            default:
                log.warn("不支持的过滤操作：{}", filter.getOperator());
        }
    }

    /**
     * 分页结果转换
     */
    public static <T, R> IPage<R> convertPage(IPage<T> sourcePage, Function<T, R> converter) {
        if (sourcePage == null) {
            return new Page<>();
        }
        
        List<R> convertedRecords = sourcePage.getRecords().stream()
                .map(converter)
                .collect(Collectors.toList());
        
        Page<R> targetPage = new Page<>(sourcePage.getCurrent(), sourcePage.getSize());
        targetPage.setRecords(convertedRecords);
        targetPage.setTotal(sourcePage.getTotal());
        
        return targetPage;
    }

    /**
     * 分页结果合并
     */
    public static <T> IPage<T> mergePages(List<IPage<T>> pages) {
        if (pages == null || pages.isEmpty()) {
            return new Page<>();
        }
        
        List<T> allRecords = new ArrayList<>();
        long total = 0;
        
        for (IPage<T> page : pages) {
            if (page != null && page.getRecords() != null) {
                allRecords.addAll(page.getRecords());
                total += page.getTotal();
            }
        }
        
        Page<T> mergedPage = new Page<>(1, allRecords.size());
        mergedPage.setRecords(allRecords);
        mergedPage.setTotal(total);
        
        return mergedPage;
    }
}
